import java.util.*;

/**
 * @author LKQ
 * @date 2022/5/23 15:44
 * @description 字符串哈希，注意从大到小枚举 重复的最大长度会超时，需要使用二分查找
 */
public class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        solution.longestDupSubstring("banana");
    }

    long[] h, p;
    int n;
    public String longestDupSubstring(String s) {
        int P = 1313;
        n = s.length();
        h = new long[n + 10];
        p = new long[n + 10];
        p[0] = 1;
        for (int i = 0; i < n; i++) {
            p[i + 1] = p[i] * P;
            h[i + 1] = h[i] * P + s.charAt(i) ;
        }
        String ans = "";
        int l = 0, r = n;
        while (l <= r) {
            int mid = (l + r) / 2;
            String t = check(s, mid);
            if (t.length() != 0) {
                l = mid + 1;
            }else {
                r = mid - 1;
            }
            ans = t.length() > ans.length() ? t : ans;
        }
        return ans;
    }
    public String check(String s, int len) {
        Set<Long> set = new HashSet<>();
        for (int i = 1; i + len <= n + 1; i++) {
            int j = i + len - 1;
            long hash = h[j] - h[i - 1] * p[j - i + 1];
            if (!set.add(hash)) {
                return s.substring(i - 1, j);
            }
        }
        return "";
    }
}
